package com.snail.service.impl;

import cn.hutool.core.util.IdUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.snail.exception.BusinessException;
import com.snail.exception.ErrorCode;
import com.snail.mapper.*;
import com.snail.model.dto.BizUserTaskRecordDto;
import com.snail.model.dto.VideoWatchRequest;
import com.snail.model.pojo.*;
import com.snail.model.vo.BizOrderVo;
import com.snail.response.BaseResponse;
import com.snail.response.ResultUtils;
import com.snail.service.BizTaskService;
import com.snail.service.BizUserTaskRecordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.util.*;
import java.util.stream.Collectors;

/**
* @author Monica
* @description 针对表【biz_user_task_record(用户任务记录表)】的数据库操作Service实现
* @createDate 2025-07-23 14:30:24
*/
@Slf4j
@Service
public class BizUserTaskRecordServiceImpl extends ServiceImpl<BizUserTaskRecordMapper, BizUserTaskRecord>
    implements BizUserTaskRecordService{

    // 签到任务ID为1
    private static final Long SIGN_IN_TASK_ID = 1L;

    @Autowired
    private BizTaskService bizTaskService;

    @Autowired
    private BizUserTaskRecordMapper bizUserTaskRecordMapper;

    @Autowired
    private BizTaskMapper bizTaskMapper;

    @Autowired
    private SysTeamSubscriptionMapper sysTeamSubscriptionMapper;

    @Autowired
    private BizOrderMapper bizOrderMapper;

    @Autowired
    private BizPaymentRecordMapper bizPaymentRecordMapper;



    /**
     * 签到获取积分，签到任务ID为1，
     * TODO: 在这里固定签到任务ID为1， 后期是否需要模糊查询签到然后获取任务id
     * @param userId
     * @return
     */
    @Override
    public BaseResponse<?> signIn(Long userId) {
        if (userId == null) {
            return ResultUtils.error("请先登入");
        }

        // 1. 判断今天是否已签到
        LocalDate today = LocalDate.now();
        LocalDateTime startOfDay = today.atStartOfDay();
        LocalDateTime endOfDay = today.plusDays(1).atStartOfDay();

        LambdaQueryWrapper<BizUserTaskRecord> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(BizUserTaskRecord::getUserId, userId)
                .eq(BizUserTaskRecord::getTaskId, SIGN_IN_TASK_ID)
                .ge(BizUserTaskRecord::getStartTime, java.sql.Timestamp.valueOf(startOfDay))
                .lt(BizUserTaskRecord::getStartTime, java.sql.Timestamp.valueOf(endOfDay));

        if (this.count(wrapper) > 0) {
            return ResultUtils.error("今日已签到");
        }

        // 2. 查询获取对应签到任务积分
        BizTask signTask = bizTaskService.getById(SIGN_IN_TASK_ID);
        int points = signTask != null && signTask.getRewardPoints() != null ? signTask.getRewardPoints() : 10;

        // 3. 插入签到记录
        BizUserTaskRecord record = new BizUserTaskRecord();
        record.setUserId(userId);
        record.setTaskId(SIGN_IN_TASK_ID);
        record.setStatus(1); // 已完成
        record.setStartTime(new Date());
        record.setCompleteTime(new Date());
        record.setPointsEarned(points);
        record.setReviewStatus(1); // 已通过
        this.save(record);

        return ResultUtils.success("签到成功，获得积分：" + points);
    }


    /**
     * 获取用户积分记录
     * @param userId
     * @return
     */
    @Override
    public BaseResponse<?> getUserPointsRecord(Long userId) {
        // 1. 联表查询用户任务记录和任务信息
        List<BizUserTaskRecordDto> allRecords = baseMapper.selectUserTaskRecordWithTaskInfo(userId);

        // 2. 当前总积分（当前年份内）用 Java Stream 对所有记录进行处理
        LocalDate now = LocalDate.now();
        LocalDate yearStart = LocalDate.of(now.getYear(), 1, 1);
        LocalDate yearEnd = LocalDate.of(now.getYear(), 12, 31).plusDays(1); // 下一年的第一天

        LocalDateTime yearStartDateTime = yearStart.atStartOfDay();
        LocalDateTime yearEndDateTime = yearEnd.atStartOfDay();

        int totalPoints = allRecords.stream()
                .filter(r -> {
                    Date createTime = r.getCreateTime();
                    if (createTime == null) {
                        return false;
                    }
                    LocalDateTime time = createTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                    return !time.isBefore(yearStartDateTime) && time.isBefore(yearEndDateTime); // 只统计当前年份的记录
                })
                .mapToInt(r -> r.getPointsEarned() == null ? 0 : r.getPointsEarned())
                .sum();

        // 3. 本月获得积分
        LocalDate firstDay = now.withDayOfMonth(1);
        LocalDateTime monthStart = firstDay.atStartOfDay();
        LocalDateTime monthEnd = now.plusMonths(1).withDayOfMonth(1).atStartOfDay();

        // 使用 Stream 过滤出本月完成的记录：
        int monthPoints = allRecords.stream()
                .filter(r -> {
                    Date completeTime = r.getCompleteTime();
                    if (completeTime == null) {
                        return false;
                    }
                    LocalDateTime time = completeTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
                    return !time.isBefore(monthStart) && time.isBefore(monthEnd);
                })
                .mapToInt(r -> r.getPointsEarned() == null ? 0 : r.getPointsEarned())
                .sum();

        // 4. 返回所有记录、总积分、本月积分
        Map<String, Object> result = new HashMap<>();
        result.put("records", allRecords);
        result.put("totalPoints", totalPoints);
        result.put("monthPoints", monthPoints);

        return ResultUtils.success(result);
    }



    /**
     * 获取用户积分任务完成的日历记录
     * @param userId
     * @param month
     * @return
     */
    @Override
    public BaseResponse<?> getUserCalendarRecords(Long userId, String month) {
        // 1. 解析月份
        LocalDate firstDay;
        if (month != null && month.matches("\\d{4}-\\d{2}")) {
            firstDay = LocalDate.parse(month + "-01");
        } else {
            firstDay = LocalDate.now().withDayOfMonth(1);
        }
        LocalDate lastDay = firstDay.plusMonths(1);

        // 2. 查询本月所有已完成任务记录（连表查任务名）
        List<BizUserTaskRecord> records = this.lambdaQuery()
                .eq(BizUserTaskRecord::getUserId, userId)
                .eq(BizUserTaskRecord::getStatus, 1)
                .ge(BizUserTaskRecord::getCompleteTime, java.sql.Timestamp.valueOf(firstDay.atStartOfDay()))
                .lt(BizUserTaskRecord::getCompleteTime, java.sql.Timestamp.valueOf(lastDay.atStartOfDay()))
                .list();

        // 查询所有涉及到的任务ID对应的任务名称
        Set<Long> taskIds = records.stream().map(BizUserTaskRecord::getTaskId).collect(Collectors.toSet());
        Map<Long, String> taskNameMap = new HashMap<>();
        if (!taskIds.isEmpty()) {
            List<BizTask> tasks = bizTaskService.listByIds(taskIds);
            for (BizTask t : tasks) {
                taskNameMap.put(t.getId(), t.getTaskName());
            }
        }

        // 3. 按天分组，收集任务名称
        Map<String, List<String>> dayTaskMap = new HashMap<>();
        for (BizUserTaskRecord record : records) {
            if (record.getCompleteTime() == null) continue;
            LocalDate day = record.getCompleteTime().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
            String dayStr = day.toString(); // yyyy-MM-dd
            String taskName = taskNameMap.getOrDefault(record.getTaskId(), "任务");
            dayTaskMap.computeIfAbsent(dayStr, k -> new ArrayList<>()).add(taskName);
        }

        // 4. 返回格式：{ \"2025-07-01\": [\"签到\", \"学习视频\"], ... }
        return ResultUtils.success(dayTaskMap);
    }


    // 阈值与 task_id 的映射（可放配置表/配置文件/数据库）
    private static final Map<Integer, Long> THRESHOLD_TASKID = Map.of(
            100, 10001L,
            300, 10002L,
            500, 10003L
    );

    @Override
    public BaseResponse<?> awardVideoWatchPoints(VideoWatchRequest request) {

        Long userId = request.getUserId();
        long threshold = request.getThreshold();
        System.out.println("threshold:" + threshold);
        System.out.println("userId:" + userId);
        // 1. 匹配 task_id
        Long taskId = THRESHOLD_TASKID.get((int)threshold);
        if (taskId == null) {
            return ResultUtils.error("无效的积分阈值");
        }
        System.out.println("taskId:" + taskId);
        // 2. 查 biz_task 获取 reward_points
        BizTask task = bizTaskMapper.selectById(taskId);
        if (task == null) {
            return ResultUtils.error("任务不存在");
        }
        int points = task.getRewardPoints();

        // 3. 检查当天是否已发放过该档位积分
        int count = bizUserTaskRecordMapper.countTodayVideoPoints(userId, taskId);
        if (count > 0) {
            return ResultUtils.error("今日观看视频时间"+threshold/100+"分钟积分已发放");
        }

        // 4. 插入积分记录
        BizUserTaskRecord record = new BizUserTaskRecord();
        record.setUserId(userId);
        record.setTaskId(taskId);
        record.setStatus(1);
        record.setCompleteTime(new Date());
        record.setPointsEarned(points);
        record.setCreateTime(new Date());
        record.setUpdateTime(new Date());
        bizUserTaskRecordMapper.insert(record);

        return ResultUtils.success("观看视频时长满"+threshold/100+"分钟，获得积分+" + points);
    }

    private static final long taskId = 10004L;

    /**
     * TODO: 订阅任务,积分订阅之后生成订单和支付记录，更新订阅表
     * @param userId
     * @return
     */

    @Override
    @Transactional
    public BaseResponse<?> subscribeTask(Long userId, Long team_id) {
        // 参数校验
        if (userId == null || team_id == null) {
            return ResultUtils.error("用户ID和团队ID不能为空");
        }

        // 查询任务信息
        BizTask task = bizTaskMapper.selectById(taskId);
        if (task == null) {
            return ResultUtils.error("任务不存在");
        }

        // 检查任务是否需要积分
        if (task.getRewardPoints() == null || task.getRewardPoints() >= 0) {
            return ResultUtils.error("任务不需要积分或积分设置不正确");
        }

//        // 验证任务是否属于指定团队
//        if (!team_id.equals(task.getTeamId())) {
//            return ResultUtils.error("任务与团队不匹配");
//        }

        // 查询用户当前积分（只累计当前年份的所做任务积分）
        LocalDate now = LocalDate.now();
        LocalDate yearStart = LocalDate.of(now.getYear(), 1, 1);
        LocalDate yearEnd = LocalDate.of(now.getYear(), 12, 31).plusDays(1); // 下一年的第一天

        LocalDateTime yearStartDateTime = yearStart.atStartOfDay();
        LocalDateTime yearEndDateTime = yearEnd.atStartOfDay();

        // 查询当前年份内的所有任务记录
        List<BizUserTaskRecord> userRecords = this.lambdaQuery()
                .eq(BizUserTaskRecord::getUserId, userId)
                .ge(BizUserTaskRecord::getCreateTime, java.sql.Timestamp.valueOf(yearStartDateTime))
                .lt(BizUserTaskRecord::getCreateTime, java.sql.Timestamp.valueOf(yearEndDateTime))
                .list();

        // 计算当前年份总积分
        int userPoints = userRecords.stream()
                .mapToInt(record -> record.getPointsEarned() != null ? record.getPointsEarned() : 0)
                .sum();

        // 检查用户积分是否足够
        int requiredPoints = Math.abs(task.getRewardPoints());
        if (userPoints < requiredPoints) {
            return ResultUtils.error("积分不足，无法订阅该任务。当前积分：" + userPoints + "，需要积分：" + requiredPoints);
        }

        // 检查用户是否已经订阅过该任务
        LambdaQueryWrapper<BizUserTaskRecord> checkWrapper = new LambdaQueryWrapper<>();
        checkWrapper.eq(BizUserTaskRecord::getUserId, userId)
                .eq(BizUserTaskRecord::getTaskId, taskId)
                .eq(BizUserTaskRecord::getTeamId, team_id)
                .in(BizUserTaskRecord::getStatus, Arrays.asList(0, 1)); // 0-待进行，1-进行中

        if (bizUserTaskRecordMapper.selectCount(checkWrapper) > 0) {
            return ResultUtils.error("您已经订阅过该任务");
        }

        // 创建订单记录
        BizOrderVo orderVo = new BizOrderVo();
        orderVo.setUserId(userId);
        orderVo.setTeamId(task.getTeamId());
        orderVo.setOrderType(1); // 订阅类型
        orderVo.setAmount(new BigDecimal(requiredPoints));
        orderVo.setGoodsIds(String.valueOf(team_id));
        orderVo.setTeamId(team_id);

        // 复用订单服务创建订单的逻辑
        BizOrder bizOrder = saveOrder(orderVo);

        // 创建支付记录
        BizPaymentRecord payRecord = createPayRecord(bizOrder);

        // 创建用户任务记录（积分扣减记录）
        BizUserTaskRecord record = new BizUserTaskRecord();
        record.setUserId(userId);
        record.setTaskId(taskId);
        record.setTeamId(task.getTeamId());
        record.setStatus(1); // 进行中
        record.setPointsEarned(task.getRewardPoints()); // 扣减积分为负值
        record.setStartTime(new Date());
        record.setCreateTime(new Date());
        record.setUpdateTime(new Date());
//        record.setDescription("订阅任务扣减积分");

        bizUserTaskRecordMapper.insert(record);

        // 更新支付记录状态为已支付
        payRecord.setStatus(1); // 已支付
        payRecord.setPaymentMethod(4); // 积分支付
        payRecord.setPaymentTime(LocalDateTime.now());
        payRecord.setTradeNo("POINT_" + payRecord.getPayNo()); // 积分支付交易号

        int payUpdateResult = bizPaymentRecordMapper.updateById(payRecord);
        if (payUpdateResult <= 0) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新支付记录失败");
        }

        // 更新订单状态为已支付
        bizOrder.setStatus(1); // 已支付
        bizOrder.setPaymentMethod(4); // 积分支付
        bizOrder.setPaymentTime(LocalDateTime.now());
        bizOrder.setTransactionId("POINT_" + bizOrder.getOrderNo()); // 积分支付交易ID

        int orderUpdateResult = bizOrderMapper.updateById(bizOrder);
        if (orderUpdateResult <= 0) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "更新订单失败");
        }

        // 更新订阅表状态为已生效(1)
        LambdaQueryWrapper<SysTeamSubscription> subscriptionWrapper = new LambdaQueryWrapper<>();
        subscriptionWrapper.eq(SysTeamSubscription::getUserId, userId)
                .eq(SysTeamSubscription::getTeamId, task.getTeamId());

        // 先查询是否存在订阅记录
        SysTeamSubscription existingSubscription = sysTeamSubscriptionMapper.selectOne(subscriptionWrapper);

        if (existingSubscription != null) {
            // 如果存在，则更新状态和时间
            existingSubscription.setStatus(1); // 设置为已生效
            existingSubscription.setStartTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
            existingSubscription.setEndTime(Date.from(LocalDateTime.now().plusMonths(1).atZone(ZoneId.systemDefault()).toInstant()));
            existingSubscription.setUpdateTime(LocalDateTime.now());
            sysTeamSubscriptionMapper.updateById(existingSubscription);
        } else {
            // 如果不存在，则创建新的订阅记录
            SysTeamSubscription newSubscription = new SysTeamSubscription();
            newSubscription.setTeamId(task.getTeamId()); // 使用任务关联的团队ID
            newSubscription.setUserId(userId);
            newSubscription.setStatus(1); // 设置为已生效
            newSubscription.setStartTime(Date.from(LocalDateTime.now().atZone(ZoneId.systemDefault()).toInstant()));
            newSubscription.setEndTime(Date.from(LocalDateTime.now().plusMonths(1).atZone(ZoneId.systemDefault()).toInstant()));
            newSubscription.setCreateTime(LocalDateTime.now());
            newSubscription.setUpdateTime(LocalDateTime.now());
            newSubscription.setTeamId(team_id);
            sysTeamSubscriptionMapper.insert(newSubscription);
        }

        // 记录积分变动日志
        log.info("用户 {} 使用 {} 积分订阅任务 {}, 任务ID: {}, 团队ID: {}",
                userId, requiredPoints, task.getTaskName(), taskId, task.getTeamId());

        return ResultUtils.success("订阅成功，扣除积分：" + requiredPoints);
    }

    // 复用BizOrderServiceImpl中的订单创建逻辑
    private BizOrder saveOrder(BizOrderVo bizOrderVo) {
        // 生成订单编号,雪花算法
        String orderNo = IdUtil.getSnowflake(1, 1).nextIdStr();
        BizOrder bizOrder = new BizOrder();
        BeanUtils.copyProperties(bizOrderVo, bizOrder);
        bizOrder.setOrderNo(orderNo);
        bizOrder.setStatus(0);
        bizOrder.setAmount(bizOrderVo.getAmount());
        int flag = bizOrderMapper.insert(bizOrder);
        if (flag <= 0) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "订单创建失败");
        }
        return bizOrder;
    }

    // 复用BizOrderServiceImpl中的支付记录创建逻辑
    private BizPaymentRecord createPayRecord(BizOrder bizOrder) {
        if (bizOrder == null) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "订单不存在");
        }
        // 生成支付记录
        BizPaymentRecord payRecord = new BizPaymentRecord();
        String payNo = IdUtil.getSnowflake(1, 1).nextIdStr();
        payRecord.setPayNo(payNo);
        payRecord.setOrderId(bizOrder.getId());
        payRecord.setAmount(bizOrder.getAmount());
        payRecord.setStatus(0);
        int flag = bizPaymentRecordMapper.insert(payRecord);
        if (flag <= 0) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "支付记录创建失败");
        }
        return payRecord;
    }




}






